const fs = require('fs');
const path = require('path');
const turf = require('@turf/turf');

/**
 * 计算GeoJSON的边界框
 * @param {object} geoJson GeoJSON对象
 * @returns {array} 边界框数组 [minLon, minLat, maxLon, maxLat]
 */
function calculateBBox(geoJson) {
    // 确保输入是有效的GeoJSON格式
    const validGeoJson = {
        type: geoJson.type,
        coordinates: geoJson.coordinates
    };
    
    // 使用turf计算边界框
    return turf.bbox(validGeoJson);
}

/**
 * 生成网格
 * @param {object} geoJson 原始城市面的GeoJSON数据
 * @param {array} bbox 边界框数组 [minLon, minLat, maxLon, maxLat]
 * @param {number} gridSizeMeters 网格大小（米）
 * @returns {array} 过滤后的网格数组，每个网格是 [minLon, minLat, maxLon, maxLat] 格式
 */
function generateGrid(geoJson, bbox, gridSizeMeters) {
    const [minLon, minLat, maxLon, maxLat] = bbox;
    
    // 计算边界框的中心点
    const center = [(minLon + maxLon) / 2, (minLat + maxLat) / 2];
    
    // 计算在当前纬度下，4km大约相当于多少度
    const metersPerDegreeLat = 111320; // 纬度方向上1度约等于111.32km
    const metersPerDegreeLon = 111320 * Math.cos((center[1] * Math.PI) / 180); // 经度方向上的1度随纬度变化
    
    // 计算网格大小的度数（取较小值以确保网格大小不超过指定的米数）
    const gridSizeDegrees = Math.min(
        gridSizeMeters / metersPerDegreeLat,
        gridSizeMeters / metersPerDegreeLon
    );
    
    // 生成网格
    const grid = turf.squareGrid(bbox, gridSizeDegrees, {
        units: 'degrees'
    });
    
    // 确保原始geoJson是Feature或FeatureCollection格式
    let cityFeatures = [];
    if (geoJson.type === 'Feature') {
        cityFeatures = [geoJson];
    } else if (geoJson.type === 'FeatureCollection') {
        cityFeatures = geoJson.features;
    } else if (geoJson.type === 'Polygon' || geoJson.type === 'MultiPolygon') {
        // 如果只是几何对象，转换为Feature
        cityFeatures = [{ type: 'Feature', properties: {}, geometry: geoJson }];
    }
    
    // 提取并过滤网格：只保留与城市面相交的网格
    const filteredGrids = [];
    grid.features.forEach(feature => {
        // 检查这个网格是否与任何城市面相交
        let intersects = false;
        
        for (const cityFeature of cityFeatures) {
            try {
                // 使用turf.booleanIntersects检查相交性
                if (turf.booleanIntersects(feature, cityFeature)) {
                    intersects = true;
                    break;
                }
            } catch (error) {
                console.warn('检查网格相交性时出错:', error.message);
                // 如果检查失败，保守处理，保留这个网格
                intersects = true;
                break;
            }
        }
        
        if (intersects) {
            const gridBBox = turf.bbox(feature);
            filteredGrids.push(gridBBox);
        }
    });
    
    return filteredGrids;
}

/**
 * 将边界框对象转换为数组格式
 * @param {object} bboxObj 包含minLon, minLat, maxLon, maxLat的对象
 * @returns {array} 边界框数组 [minLon, minLat, maxLon, maxLat]
 */
function bboxObjToArray(bboxObj) {
    return [bboxObj.minLon, bboxObj.minLat, bboxObj.maxLon, bboxObj.maxLat];
}

/**
 * 主函数
 */
async function main() {
    const geoDir = path.join(__dirname, '各地市geo');
    const gridSizeMeters = 4000; // 4km
    const outputResults = {};
    
    try {
        // 读取目录中的所有文件
        const files = fs.readdirSync(geoDir).filter(file => file.endsWith('.json'));
        
        console.log(`找到 ${files.length} 个GeoJSON文件`);
        
        // 处理每个文件
        for (const file of files) {
            const cityName = file.replace('.json', '');
            const filePath = path.join(geoDir, file);
            
            console.log(`处理文件: ${file}`);
            
            try {
                // 读取并解析GeoJSON文件
                const geoJson = JSON.parse(fs.readFileSync(filePath, 'utf8'));
                
                // 计算边界框 [minLon, minLat, maxLon, maxLat]
                const bbox = calculateBBox(geoJson);
                console.log(`  ${cityName} 边界:`, bbox);
                
                // 生成网格（传入原始geoJson用于过滤）
                const grids = generateGrid(geoJson, bbox, gridSizeMeters);
                console.log(`  生成了 ${grids.length} 个4km×4km网格（已过滤掉城市面外的网格）`);
                
                // 保存结果
                outputResults[cityName] = {
                    city: cityName,
                    originalBBox: bbox,  // 数组格式 [minLon, minLat, maxLon, maxLat]
                    gridCount: grids.length,
                    grids: grids         // 每个网格都是 [minLon, minLat, maxLon, maxLat] 格式
                };
                
            } catch (error) {
                console.error(`处理文件 ${file} 时出错:`, error.message);
                outputResults[cityName] = {
                    city: cityName,
                    error: error.message
                };
            }
        }
        
        // 保存结果到文件
        const outputPath = path.join(__dirname, 'grid_results.json');
        fs.writeFileSync(outputPath, JSON.stringify(outputResults, null, 2), 'utf8');
        console.log(`\n结果已保存到: ${outputPath}`);
        
        // 输出统计信息
        console.log('\n统计信息:');
        Object.values(outputResults).forEach(result => {
            if (result.error) {
                console.log(`${result.city}: 处理失败 - ${result.error}`);
            } else {
                console.log(`${result.city}: 生成了 ${result.gridCount} 个网格`);
                // 显示前两个网格作为示例
                if (result.grids && result.grids.length > 0) {
                    console.log(`  前两个网格示例:`, result.grids.slice(0, 2));
                }
            }
        });
        
    } catch (error) {
        console.error('处理过程中出错:', error.message);
    }
}

// 运行主函数
main();